/*-----------------------------------------------------------------------
					 \\\|///
				   \\  - -  //
					(  @ @  )
+-----------------------------oOOo-(_)-oOOo-----------------------------+
CONFIDENTIAL IN CONFIDENCE
This confidential and proprietary software may be only used as authorized
by a licensing agreement from CrazyBingo (Thereturnofbingo).
In the event of publication, the following notice is applicable:
Copyright (C) 2012-20xx CrazyBingo Corporation
The entire notice above must be reproduced on all authorized copies.
Author				:		CrazyBingo
Technology blogs 	: 		http://blog.chinaaet.com/crazybingo
Email Address 		: 		thereturnofbingo@gmail.com
Filename			:		key_jitter_scan.v
Data				:		2011-06-26
Description			:		Key scan via jitter detect. 
Modification History	:
Data			By			Version			Change Description
=========================================================================
11/06/26		CrazyBingo	1.0				Original
13/10/27		CrazyBingo	2.0				Modification
-------------------------------------------------------------------------
|                                     Oooo								|
+-------------------------------oooO--(   )-----------------------------+
                            (   )   ) /
                             \ (   (_/
                              \_)
-----------------------------------------------------------------------*/

`timescale 1ns/1ns
module key_jitter_scan#(
		   parameter	KEY_WIDTH = 4
	   ) (
		   //global clock
		   input wire clk,
		   input wire rst_n,
		   //key interface
		   input wire [ KEY_WIDTH - 1: 0 ] key_data,
		   //user interface
		   output	wire key_flag,
		   output	reg	[ KEY_WIDTH - 1: 0 ] key_value	//H Valid
	   );

//-----------------------------------
//Delay for 20ms
localparam DELAY_TOP = 20'd1000_000;
//localparam DELAY_TOP = 20'd1000;		//Just for test
reg	[ 19: 0 ] delay_cnt;
always@( posedge clk or negedge rst_n ) begin
	if ( !rst_n )
		delay_cnt <= 0;
	else if ( delay_cnt < DELAY_TOP - 1'b1 )
		delay_cnt <= delay_cnt + 1'b1;
	else
		delay_cnt <= 0;
end
wire	delay_done = ( delay_cnt == DELAY_TOP - 1'b1 ) ? 1'b1 : 1'b0;

//-----------------------------------
//Key scan via jitter detect.
localparam	SCAN_DETECT1	= 3'd0;
localparam	SCAN_JITTER1	= 3'd1;
localparam	SCAN_READ		= 3'd2;
localparam	SCAN_DETECT2	= 3'd3;
localparam	SCAN_JITTER2	= 3'd4;
reg	[ 2: 0 ] key_state;
always@( posedge clk or negedge rst_n ) begin
	if ( !rst_n ) begin
		key_state <= SCAN_DETECT1;
		key_value <= { KEY_WIDTH{ 1'b0 } };
	end
	else if ( delay_done ) begin
		case ( key_state )
			SCAN_DETECT1:   	//Detect if there is key down
			begin
				if ( key_data != { KEY_WIDTH{ 1'b1 } } )
					key_state <= SCAN_JITTER1;
				else
					key_state <= SCAN_DETECT1;
			end
			SCAN_JITTER1:   	//Delay 20 ms and detect again
			begin
				if ( key_data != { KEY_WIDTH{ 1'b1 } } )
					key_state <= SCAN_READ;
				else
					key_state <= SCAN_DETECT1;
			end
			SCAN_READ:   		//Save the detect key value
			begin
				key_value <= ~key_data; //lock the key_value
				key_state <= SCAN_DETECT2;
			end
			SCAN_DETECT2:   	//Detect if the key is open
			begin
				if ( key_data == { KEY_WIDTH{ 1'b1 } } )
					key_state <= SCAN_JITTER2;
				else
					key_state <= SCAN_DETECT2;
			end
			SCAN_JITTER2:   	//Delay 20ms and detect again
			begin
				if ( key_data == { KEY_WIDTH{ 1'b1 } } )
					key_state <= SCAN_DETECT1;
				else
					key_state <= SCAN_JITTER2;
			end
		endcase
	end
	else begin
		key_state <= key_state;
		key_value <= key_value;
	end
end

//---------------------------------------
//output the capture enable signal
assign key_flag = ( key_state == SCAN_JITTER2 && delay_done == 1'b1 ) ? 1'b1 : 1'b0;

endmodule
